import {messages} from "share/common";
import React, { Component } from 'react';
import { message } from 'antd'
import FlowContainer from './flow-container'
import { allNodeList, nodeTypes } from './node-list'
import workflowUtil from 'containers/setting/new-workflow/utils'
/**
 * 简易流程图组件，为什么说是简易，因为我之前做了个可以自由拖动的结果需求变了
 * 为了抗拒这种行为，我给这个组件加上 'simple' 字段，虽然产品看不到
 * 这是个流程图组件，给定两个数组直接渲染出对应的流程图
 * 这个结构是后端定的，如果后期后端不是这种字段，你就怼他，让他重新提需求
 *
 * 说明：
 * 这个流程图的思路简单来说就是拆分子流程然后分栏渲染
 * 因为有子流程，所以你能看到很多递归，要改算法请十分小心
 * 先根据子流程计算每个组件的行数和该行内的列数
 * 然后使用行列组件（flow-grid）进行计算，并进行初步渲染节点（flow-node）
 * 等节点都渲染到位置上后，根据节点位置渲染箭头（flow-arrow)
 * 节点的添加和删除也处理好并把结果传给外部
 * 外部应该只需要进行第一轮的数据筛选和节点属性的存储和更改操作
 *
 */
class SimpleFlow extends Component {

  constructor(props) {
    super(props);
    this.state = {
      nodes: [
        { type: nodeTypes.START, id: 'start', title: messages('setting.key1939')/*开始*/, viewMap: {}, },
        { type: nodeTypes.END, id: 'end', title: messages('setting.key1252')/*结束*/, viewMap: {},}
      ],
      routes: [
        { from: 'start', to: 'end' }
      ],
      id: workflowUtil.getRandomUUID(),
      deleteNodes: [],//将要删掉的节点
    }
  }

  componentDidMount() {
    const { nodes, routes, isChange } = this.props;
    this.setState({ nodes, routes, isChange })
  }

  componentWillReceiveProps(nextProps) {
    const { nodes, routes, isChange } = nextProps;
    this.setState({ nodes, routes, isChange })
  }

  componentWillMount() {
    // 拦截判断是否离开当前页面
    window.addEventListener('beforeunload', this.beforeunload);
  }

  componentWillUnmount() {
    // 销毁拦截判断是否离开当前页面
    window.removeEventListener('beforeunload', this.beforeunload);
  }

  beforeunload = (e) => {
    let confirmationMessage = messages('components.key908')/*你确定离开此页面吗?*/;
    (e || window.event).returnValue = confirmationMessage;
    return confirmationMessage;
  };

  handleAddNode = (type, value, next) => {
    const { nodes, routes } = this.state;
    let { id } = this.state;
    const { valueKey, showValueKey, readOnly } = this.props;
    if (readOnly) {
      return
    }
    let resultRoute = [];
    let sourceRoutes = [].concat(routes);
    let map = {};
    nodes.map(node => {
      map[node[valueKey]] = node;
    });
    let tempNodes = JSON.parse(JSON.stringify(nodes));
    if (type === nodeTypes.OPEN) {
      //添加条件，将下方子流程所有节点添加至左侧条件下，右侧条件设空流程
      let open = workflowUtil.getRandomUUID();
      let c1 = workflowUtil.getRandomUUID();
      let c2 = workflowUtil.getRandomUUID();
      let close = workflowUtil.getRandomUUID();
      tempNodes.push({ type: nodeTypes.OPEN, [valueKey]: open, [showValueKey]: '', route: close });
      tempNodes.push({ type: nodeTypes.CONDITION, [valueKey]: c1, [showValueKey]: messages('components.key881')/*条件1*/, priority: 1 });
      tempNodes.push({ type: nodeTypes.CONDITION, [valueKey]: c2, [showValueKey]: messages('components.key882')/*条件2*/, priority: 2 });
      tempNodes.push({ type: nodeTypes.CLOSE, [valueKey]: close, [showValueKey]: '', route: open });
      routes.map(route => {
        if (route.from === value) {
          resultRoute.push({ from: route.from, to: open });
          resultRoute.push({ from: open, to: c1 });
          resultRoute.push({ from: open, to: c2 });
          if (map[route.to].type === nodeTypes.END || map[route.to].type === nodeTypes.CLOSE || (next && next === 'next')) {
            resultRoute.push({ from: c1, to: close });
            resultRoute.push({ from: c2, to: close });
            resultRoute.push({ from: close, to: route.to });
            sourceRoutes = this.deleteRouteByRoute(route, sourceRoutes);
          } else {
            resultRoute.push({ from: c1, to: route.to });
            resultRoute.push({ from: c2, to: close });
            let last = this.getEscapeRoute(value, sourceRoutes, map);
            resultRoute.push({ from: last.from, to: close });
            resultRoute.push({ from: close, to: last.to });
            sourceRoutes = this.deleteRouteByRoute(route, sourceRoutes);
            sourceRoutes = this.deleteRouteByRoute(last, sourceRoutes);
          }
        }
      });
      this.props.onSelectNode(null);
    } else if (type === nodeTypes.CONDITION) {
      //添加条件分支，直接加一个节点两个路由就行了
      let nodeId = workflowUtil.getRandomUUID();
      let count = 1;
      routes.map(route => {
        if (route.from === value)
          count++;
      });
      tempNodes.push({ type: nodeTypes.CONDITION, [valueKey]: nodeId, [showValueKey]: `${messages('setting.key1330')/*条件*/}${count}`, priority: count });
      resultRoute.push({ from: value, to: nodeId });
      resultRoute.push({ from: nodeId, to: map[value].route });
    } else {
      //普通节点，替换当前路由为新节点的路由
      let nodeId = workflowUtil.getRandomUUID();
      tempNodes.push({ type, [valueKey]: nodeId, [showValueKey]: allNodeList.find(node => node.type === type).title });
      routes.map(route => {
        if (route.from === value) {
          resultRoute.push({ from: route.from, to: nodeId });
          resultRoute.push({ from: nodeId, to: route.to });
          sourceRoutes = this.deleteRouteByRoute(route, sourceRoutes);
        }
      });
      this.props.onSelectNode(nodeId);
    }
    let targetRoutes = sourceRoutes.concat(resultRoute);
    this.setState({ id });
    this.props.onChange(tempNodes, targetRoutes);
  };

  /**
   * 得到当前节点所在的最小子流程的起始节点
   * @param value 当前节点
   * @param routes 路由数组
   * @param map 节点map
   * @return {*} 结束节点
   */
  getTreeEnd = (value, routes, map) => {
    let nowNode = value;
    let startNode = '';
    let endNode = '';
    let target = '';
    let routeCount = 0;
    Object.keys(map).map(key => {
      if (map[key].type === nodeTypes.START)
        startNode = key;
      if (map[key].type === nodeTypes.END)
        endNode = key;
    });
    //向下寻找，遇到第一个同级close、end则为最终结束节点
    while(true) {
      for(let i = 0; i < routes.length; i++) {
        let route = routes[i];
        if (route.from === nowNode) {
          nowNode = route.to;
          break;
        }
      }
      if (map[nowNode].type === nodeTypes.OPEN) {
        routeCount++;
      }
      if (map[nowNode].type === nodeTypes.CLOSE || map[nowNode].type === nodeTypes.END) {
        if (routeCount === 0) {
          target = nowNode;
          break;
        } else {
          routeCount--;
        }
      }
    }
    return target;
  };

  /**
   * 得到当前节点所在的最小子流程的逃出路由
   * @param value 当前节点
   * @param routes 路由数组
   * @param map 节点map
   * @return {*} 逃出路由
   */
  getEscapeRoute = (value, routes, map) => {
    //得到逃出节点的终点
    let target = this.getTreeEnd(value, routes, map);
    let nowNode = value;
    let result = null;
    let nextRoute = {};
    while(true) {
      for(let i = 0; i < routes.length; i++) {
        let route = routes[i];
        if (route.from === nowNode) {
          nextRoute = route;
          if (route.to === target)
            result = route;
          break;
        }
      }
      if (result)
        break;
      else {
        nowNode = nextRoute.to;
      }
    }
    return result;
  };

  deleteRouteByRoute = (route, routes) => {
    routes.map((r, i) => {
      if (r.from === route.from && r.to === route.to)
        routes.splice(i, 1);
    });
    return routes;
  };

  /**
   * 得到当前子流程下所有节点的数组
   * @param value 子流程起点
   * @param map 节点map
   * @param endNode 子流程终点（可选）
   * @return {Array}
   */
  getTreeNodesFrom = (value, map, endNode) => {
    const { valueKey } = this.props;
    let nowNode = map[value];
    let routeCount = 0;
    let result = [];
    result.push(value);
    while(true) {
      //碰到结束节点直接跳出
      if (nowNode[valueKey] === endNode)
        break;
      if (nowNode.type === nodeTypes.OPEN) {
        routeCount++;
        nowNode.to.map(t => {
          result = result.concat(this.getTreeNodesFrom(t, map));
        });
        nowNode = map[nowNode.route];
      } else if (nowNode.type === nodeTypes.CLOSE) {
        if (routeCount === 0) {
          result.pop();
          break;
        } else {
          if (nowNode.type === nodeTypes.CLOSE && routeCount === 0) {
            result.pop();
            break;
          }
          routeCount--;
          nowNode = map[nowNode.to[0]];
        }
      } else if (nowNode.type === nodeTypes.END) {
        break;
      } else {
        nowNode = map[nowNode.to[0]];
      }
      result.push(nowNode[valueKey]);
    }
    //数组去重
    result = result.filter((item, index, self) => self.indexOf(item) === index);
    return result;
  };

  handleDeleteNode = (value, type = null, status = '') => {
    const { nodes, routes } = this.state;
    let tempNodes = JSON.parse(JSON.stringify(nodes));
    const { valueKey, onChange, onSelectNode } = this.props;
    let map = {};
    tempNodes.map(node => {
      node.from = [];
      node.to = [];
      routes.map(route => {
        if (route.from === node[valueKey])
          node.to.push(route.to);
        if (route.to === node[valueKey])
          node.from.push(route.from);
      });
      map[node[valueKey]] = node;
    });
    let node = map[value];
    let sourceRoutes = JSON.parse(JSON.stringify(routes));
    let resultRoutes = [];
    if (allNodeList.find(n => node.type === n.type).manually) {
      //普通节点
      tempNodes.map((node, i) => {
        if (node[valueKey] === value)
          tempNodes.splice(i, 1);
      });
      let from = '', to = '';
      routes.map(route => {
        if (route.from === value) {
          to = route.to;
          sourceRoutes = this.deleteRouteByRoute(route, sourceRoutes);
        }
        if (route.to === value) {
          from = route.from;
          sourceRoutes = this.deleteRouteByRoute(route, sourceRoutes);
        }
      });
      resultRoutes.push({ from, to });
    } else if (node.type === nodeTypes.OPEN) {
      //条件开始节点
      let deleteNodes = this.getTreeNodesFrom(value, map, node.route);
      tempNodes = tempNodes.filter(n => deleteNodes.indexOf(n[valueKey]) === -1);
      if (type === 'OPEN') {
        if (status === 'cancel') {
          this.setState({ deleteNodes: [] })
        } else {
          this.setState({ deleteNodes })
        }
        return
      } else {
        sourceRoutes = this.deleteRoutesByNodes(deleteNodes, sourceRoutes);
        resultRoutes.push({ from: node.from[0], to: map[node.route].to[0] });
        // this.setState({ deleteNodes:[] })
      }
    } else {
      //条件节点
      let open = node.from[0];
      let close = map[open].route;
      let sameSpanCondition = [];
      //如果同级只有两个条件，那么最后会留下另一条上面的所有节点
      if (map[open].to.length === 2) {
        let openFrom = map[open].from[0];
        let anotherCondition = map[open].to.find(node => node !== value);
        let closeTo = map[close].to[0];
        //如果另一边只有一个条件节点，则直接删除整个条件
        if (map[map[anotherCondition].to[0]].type === nodeTypes.CLOSE) {
          this.handleDeleteNode(open);
          return;
        } else {
          //删除一边的子流程
          let deleteNodes = this.getTreeNodesFrom(value, map);
          sourceRoutes = this.deleteRoutesByNodes(deleteNodes, sourceRoutes);
          tempNodes = tempNodes.filter(n => deleteNodes.indexOf(n[valueKey]) === -1);
          //删除另一边的条件节点
          sourceRoutes = this.deleteRoutesByNodes([anotherCondition], sourceRoutes);
          tempNodes = tempNodes.filter(n => n[valueKey] !== anotherCondition);
          //删除open、close节点
          sourceRoutes = this.deleteRoutesByNodes([open, close], sourceRoutes);
          tempNodes = tempNodes.filter(n => n[valueKey] !== open && n[valueKey] !== close);
          //添加两头的路由
          resultRoutes.push({ from: openFrom, to: map[anotherCondition].to[0] });
          resultRoutes.push({ from: this.getEscapeRoute(anotherCondition, routes, map).from, to: closeTo });
        }
      } else {
        //如果多于两个条件，那么只删除当前条件下的流程
        let deleteNodes = this.getTreeNodesFrom(value, map);
        tempNodes = tempNodes.filter(n => deleteNodes.indexOf(n[valueKey]) === -1);
        sourceRoutes = this.deleteRoutesByNodes(deleteNodes, sourceRoutes);
      }
      tempNodes.map(item => {
        //同一层的条件
        if (open === item.from[0]) {
          sameSpanCondition.push(item)
        }
      });
      //同一层的条件重新排序优先级
      sameSpanCondition.sort((a, b) => a.priority < b.priority).map((item, index) => {
        item.priority = index + 1;
      });
      //将排好序的优先级赋值
      tempNodes.map(nodes => {
        sameSpanCondition.map(item => {
          if(item[valueKey] === nodes[valueKey]){
            nodes.priority = item.priority
          }
        });
      });
    }
    let tempRoutes = sourceRoutes.concat(resultRoutes);
    onChange(tempNodes, tempRoutes);
    onSelectNode(null);
  };

  deleteRoutesByNodes = (nodes, sourceRoutes) => {
    return sourceRoutes.filter(route => nodes.indexOf(route.from) === -1 && nodes.indexOf(route.to) === -1);
  };

  swapArray = (arr, index1, index2) => {
    arr[index1] = arr.splice(index2, 1, arr[index1])[0];
    return arr.filter(item => {return item !== undefined});
  };

  /**
   * 调整优先级
   * type up 左边箭头 升级 down 右边箭头 降级
   * id 当前节点id
   * */
  onChangeNodeLevel = (type, id) => {
    const { nodes, routes, valueKey } = this.props;
    let tempNodes = JSON.parse(JSON.stringify(nodes));
    let tempRoutes = JSON.parse(JSON.stringify(routes));
    const { onChange, onSelectNode } = this.props;
    let nowNode = tempNodes.find(item => item[valueKey] === id);
    let sameSpanCondition = [], arr = [], fromNodeOID = null;
    tempRoutes.map(route => {
      if (route.to === nowNode[valueKey]) {
        fromNodeOID = route.from;
      }
    });
    tempRoutes.map(route => {
      if (fromNodeOID === route.from) {
        tempNodes.map(node => {
          if (route.to === node[valueKey]) {
            sameSpanCondition.push(node);
          }
        })
      }
    });
    let indexNum = 0;
    //前端先排序
    sameSpanCondition.sort((a, b) => a.priority - b.priority).map((item, index) => {
      if (item[valueKey] === id) {
        indexNum = index;
      }
    });
    if (type === 'up') {
      if (indexNum === 0)
        return;
      arr = this.swapArray(JSON.parse(JSON.stringify(sameSpanCondition)), indexNum, indexNum - 1);
      arr.map((item, index) => {
        item.priority = index + 1
      });
    } else {
      arr = this.swapArray(JSON.parse(JSON.stringify(sameSpanCondition)), indexNum, indexNum + 1);
      arr.map((item, index) => {
        item.priority = index + 1
      });
    }
    tempNodes.map(node => {
      arr.map(item => {
        if (node[valueKey] === item[valueKey]) {
          node.priority = item.priority
        }
      })
    });
    onChange(tempNodes, routes);
    this.setState({ isChange: true });
    onSelectNode(null);
  };

  //粘贴条件 条件节点特殊处理 因为条件中有唯一的conditionOID
  handlePasteNode = (targetID) => {
    const { nodes, routes, valueKey } = this.props;
    const { onChange, onSelectNode } = this.props;
    let tempNodes = JSON.parse(JSON.stringify(nodes));
    let tempRoutes = JSON.parse(JSON.stringify(routes));
    let source = {};
    tempNodes.map(item => {
      if(!item.viewMap){
        item.viewMap = {
          copySource: 'false',
          isCanPaste: 'false',
          errorToast: 'false',
        };
      }
      if (item.viewMap.copySource === 'true') {
        source = JSON.parse(JSON.stringify(item));
        item.viewMap.copySource = 'false';
      }
    });
    tempNodes.map(item => {
      if(!item.viewMap){
        item.viewMap = {
          copySource: 'false',
          isCanPaste: 'false',
          errorToast: 'false',
        };
      }
      if (item.type === source.type) {
        item.viewMap.isCanPaste = 'false';
        if (item[valueKey] === targetID) {
          item.ruleApprovalNodeCopy = true;//给后段判断是否为复制标识
          item.viewMap.errorToast = source.viewMap.errorToast;
          if (item.type === nodeTypes.CONDITION) {
            item.remark = source.remark;
            item.ruleConditionDTO = source.ruleConditionDTO;
            let getCurrentPart = (items) => {
              for(let i = 0; i < items.length; i++) {
                let rule = items[i];
                rule.conditionOID = workflowUtil.getRandomUUID();
                if (rule.type === 2) {//条件组
                  getCurrentPart(rule.ruleConditionDTOList);
                }
              }
            };
            //复制后条件中的conditionOID重新赋值
            getCurrentPart( item.ruleConditionDTO && item.ruleConditionDTO.ruleConditionDTOList || []);
          }
          if (item.type === nodeTypes.APPROVE) {
            item.remark = source.remark;
            item.ruleBranchApprover = source.ruleBranchApprover;
            item.approvalActions = source.approvalActions;
            item.approvalIsPass = source.approvalIsPass;
            item.approvalOvertimeDay = source.approvalOvertimeDay;
            item.invoiceAllowUpdateType = source.invoiceAllowUpdateType;
            item.containsSelfApprovalSkip = source.containsSelfApprovalSkip;
            item.countersignRule = source.countersignRule;
            item.selfApprovalRule = source.selfApprovalRule;
            item.editable = source.editable;
            item.nullableRule = source.nullableRule;
            item.nodeNameI18n = source.nodeNameI18n;
          }
          if (item.type === nodeTypes.KNOWN) {
            item.remark = source.remark;
            item.notifyInfo = source.notifyInfo;
            item.notifyWay = source.notifyWay;
            item.ruleBranchApprover = source.ruleBranchApprover;
            item.nodeNameI18n = source.nodeNameI18n;
          }
        }
      }
    });
    message.success(messages('components.key901')/*粘贴成功*/);
    onChange(tempNodes, tempRoutes);
    this.setState({ isChange: true });
    onSelectNode(null);
  };

  handleCopyNode = (copy) => {
    const { nodes, routes, valueKey, onChange, onSelectNode } = this.props;
    let tempNodes = JSON.parse(JSON.stringify(nodes));
    let tempRoutes = JSON.parse(JSON.stringify(routes));
    tempNodes.map(item => {
      if(!item.viewMap){
        item.viewMap = {
          copySource: 'false',
          isCanPaste: 'false',
          errorToast: 'false',
        };
      }
      if (item[valueKey] === copy[valueKey]) {
        item.viewMap.copySource = 'true';
        item.viewMap.isCanPaste = 'true';
      } else {
        item.viewMap.copySource = 'false';
        if (copy.type === item.type) {
          item.viewMap.isCanPaste = 'true';
        } else {
          item.viewMap.isCanPaste = 'false';
        }
      }
    });
    message.success(messages('components.key902')/*复制成功*/);
    onChange(tempNodes, tempRoutes);
    this.setState({ isChange: true });
    onSelectNode(null);
  }

  render() {
    const { valueKey, nodes,clientY,clientX, routes, onSelectNode, selectedNode, showValueKey, scale, nodeList, readOnly, currentNodeOID} = this.props;
    const { deleteNodes, isChange} = this.state;
    return (
      <div style={{ width: '100%', height: '100%', overflow: 'scroll', background: '#E3E5E8' }}>
        <FlowContainer
          valueKey={valueKey}
          readOnly={readOnly}
          showValueKey={showValueKey}
          nodes={nodes}
          isChange={isChange}
          routes={routes}
          clientY={clientY}
          clientX={clientX}
          scale={scale}
          nodeList={nodeList}
          currentNodeOID={currentNodeOID}
          deleteNodes={deleteNodes}
          selectedNode={selectedNode}
          onSelectNode={onSelectNode}
          onPasteNode={this.handlePasteNode}
          onCopyNode={this.handleCopyNode}
          onMouseMove={this.onMouseMove}
          onChangeNodeLevel={this.onChangeNodeLevel}
          onDeleteNode={this.handleDeleteNode}
          onAddNode={this.handleAddNode}
        />
      </div>
    );
  }
}

SimpleFlow.propTypes = {
  showValueKey: React.PropTypes.string,
  valueKey: React.PropTypes.string.isRequired,
  nodes: React.PropTypes.array.isRequired,
  routes: React.PropTypes.array.isRequired,
  onChange: React.PropTypes.func,
  isChange: React.PropTypes.bool,//节点内容是否变化
  onSelectNode: React.PropTypes.func,
  selectedNode: React.PropTypes.any,
  style: React.PropTypes.string,
  scale: React.PropTypes.number,
  clientY: React.PropTypes.number,
  clientX: React.PropTypes.number,
  currentNodeOID: React.PropTypes.string,
  readOnly: React.PropTypes.bool,
  nodeList: React.PropTypes.any,//节点列表 改为后台取值
};

export default SimpleFlow;
